package org.nobject.common.lang;

import static org.nobject.common.lang.StringUtils.isEmpty;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.nobject.common.exception.ConvertException;
import org.nobject.common.exception.FormatException;
import org.nobject.common.exception.UnSupportException;

/**
 * 日期工具类<br>
 * 
 * DString 指 DateString
 * 
 * @author bianrongjun
 * @version 1.0
 */
public class DateUtils {
	
	/** 格式 */
	public static class Format {
		/** yyyy-MM-dd */
		public final static String YMD="yyyy-MM-dd";
		/** HH:mm:ss */
		public final static String HMS="HH:mm:ss";
		/** yyyy-MM-dd HH:mm:ss*/
		public final static String YMDHMS="yyyy-MM-dd HH:mm:ss";
	}
	
	/** 时间长度,单位-微秒 */
	public static class Size{
		/** 秒 */
		public final static long second=1000l;
		/** 分钟 */
		public final static long minute=1000*60l;
		/** 小时 */
		public final static long hour=1000*60*60l;
		/** 日期 */
		public final static long day=1000*60*60*24l;
		/** 月份 */
		public final static long month=1000*60*60*24*30l;
		/** 年 */
		public final static long year=1000*60*60*24*365l;
	}
	
	/** sdfYMDzhcn */
	public final static SimpleDateFormat sdfYMDzhcn = new SimpleDateFormat("yyyy年M月d日");
	
	/** 中文周数组 */
	public static String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
	
	/** 获取格式化对象 */
	public static SimpleDateFormat getFormatYMDHMS(){
		return  new SimpleDateFormat(Format.YMDHMS); 
	}
	
	/** 获取格式化对象 */
	public static SimpleDateFormat getFormatHMS(){
		return  new SimpleDateFormat(Format.HMS); 
	}
	
	/** 获取格式化对象 */
	public static SimpleDateFormat getFormatYMD(){
		return  new SimpleDateFormat(Format.YMDHMS); 
	}
	
	/** 
	 * 获取中文周名称
	 * @param date 时间
	 * */
	public static String getWeekInZhcn(Date date) {
		return weekDays[getCalendar(date).get(Calendar.DAY_OF_WEEK) - 1];
	}
	
	/** 
	 * 获取Calendar 获取日历
	 * @param date 日期
	 */
	public static Calendar getCalendar(Date date){
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		return c;
	}
	
	/** 
	 * 获取Calendar
	 * @param strDate 字符串
	 */
	public static Calendar getCalendar(String strDate) throws ConvertException{
		return getCalendar(toDate(strDate));
	}
	
	/** 获取当天的中文周名称 */
	public static String getNowWeekInZhcn() {return getWeekInZhcn(new Date());}

	/******************************************************************************************************************
	 * 
	 *  getDString 区域
	 * 
	 *******************************************************************************************************************/
	
	/**
	 * 获取时间字符串(yyyy-MM-dd HH:mm:ss)
	 * @param million 长整形
	 */
	public static String getDString(long million) {
		Date d = new Date();
		d.setTime(million);
		return  new SimpleDateFormat(Format.YMDHMS).format(d);
	}

	/**
	 * 获取指定日期偏移后的日期
	 * @param strDate 时间字符串
	 * @param time 偏移量
	 * @throws ConvertException 转化异常
	 */
	public static String getDString(String strDate,long time) throws ConvertException{
		Date d=toDate(strDate);
		return getDString(d.getTime()+time);
	}
	
	/** 获取当前时间字符串(yyyy-MM-dd HH:mm:ss) */
	public static String getNowDString() {return getNowDString(Format.YMDHMS);}
	
	/** 
	 * 获取当前日期字符串
	 * @param 日期格式
	 */
	public static String getNowDString(String fmt){return getNowDString(new SimpleDateFormat(fmt));}
	
	/**
	 * 获取当前日期字符串
	 * @param sdf SimpleDateFormat
	 */
	public static String getNowDString(SimpleDateFormat sdf) {return sdf.format(new Date());}
	
	/**
	 * 获取当前时间偏移后的日期字符串
	 * @param time 偏移量
	 */
	public static String getNowDString(long time){return getDString(System.currentTimeMillis()+time);}
	

	
	/******************************************************************************************************************
	 * 
	 *  Format 区域
	 * 
	 *******************************************************************************************************************/
	
	/**
	 * 格式化成年月日字符串
	 * @param strDate
	 */
	public static String format2YMD(String strDate) throws UnSupportException{
		return format2YMDHms(strDate).substring(0, 10);
	}
	
	/** 
	 * 格式化成小时分钟秒
	 * @param strDate
	 */
	public static String format2Hms(String strDate) throws UnSupportException{
		return format2YMDHms(strDate).substring(11);
	}
	
	/**
	 * 格式化成年月日小时分钟秒字符串
	 * @param strDate 日期字符串
	 */
	public static String format2YMDHms(String strDate) throws UnSupportException{
		if(StringUtils.isEmpty(strDate)) throw new RuntimeException("时间字符串不能为空");
		strDate=strDate.trim();
		if (strDate.matches("\\d{4}")) {//yyyy
			strDate += "-01-01 00:00:00";
		} else if (strDate.matches("\\d{4}-\\d{1,2}")) {//yyyy-MM
			strDate += "-01 00:00:00";
		} else if (strDate.matches("\\d{4}-\\d{1,2}-\\d{1,2}")) {//yyyy-MM-dd
			strDate += " 00:00:00";
		} else if (strDate.matches("\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}")) {//yyyy-MM-dd HH:mm
			strDate += ":00";
		}else if (strDate.matches("\\d{4}-\\d{1,2}-\\d{1,2} \\d{1,2}:\\d{1,2}:\\d{1,2}")) {//yyyy-MM-dd HH:mm:ss
		}else{
			//throw new UnSupportException("不能支持该格式的匹配:"+strDate);
		}
		return strDate;
	}
	
	/** 
	 * 格式化时间字符串
	 * @param strDate 日期字符串
	 * @param fmt 格式
	 *  */
	public static String format2(String strDate,String fmt) throws FormatException{
		try {
			return new SimpleDateFormat(fmt).format(toDate(strDate));
		} catch (Exception e) {
			throw new FormatException(e);
		}
	}
	
	/******************************************************************************************************************
	 * 
	 *  Compare 区域
	 * 
	 *******************************************************************************************************************/
	
	/**
	 * 比较日期间隔
	 * @param strDate1 日期字符串1
	 * @param strDate2 日期字符串2
	 */
	public static long compare(String strDate1,String strDate2) throws ConvertException{
		return compare(toDate(strDate1), toDate(strDate2));
	}
	
	/** 
	 * 比较日期间隔
	 * @param date1 日期1
	 * @param date2 日期2
	 */
	public static long compare(Date date1,Date date2){
		return date1.getTime()-date2.getTime();
	}
	
	/** 
	 * 与今日比较
	 * @param strDate
	 */
	public static long compareNow(String strDate) throws ConvertException{
		Date d1=toDate(strDate); 
		return d1.getTime()-new Date().getTime();
	}
	
	/******************************************************************************************************************
	 * 
	 *  Birthday,Age
	 * 
	 *******************************************************************************************************************/
	
	/**
	 * 以年龄和当前时间推断出生日期
	 * @param age 年龄
	 */
	public static String getBirthdayDString(int age){
		Calendar c=Calendar.getInstance();c.add(Calendar.YEAR, -age);
		return new SimpleDateFormat(Format.YMDHMS).format(c.getTime());
	}
	
	/**
	 * 计算生日，距离当前时间的间隔
	 * @param birthday 生日
	 */
	public static int caculateAge(String birthday) throws ConvertException{
		if(StringUtils.isEmpty(birthday)) return -1;
		long l=(System.currentTimeMillis()-toDate(birthday).getTime());
		return Integer.parseInt(l/(3600000*24*365l)+"");
	}
	
	/******************************************************************************************************************
	 * 
	 *  toDate 区域
	 * 
	 *******************************************************************************************************************/
	
	/** 
	 * 转换字符串到Date
	 * @param strDate 字符串
	 * @param fmt 格式
	 */
	public static Date toDate(String strDate,String fmt) throws ConvertException{
		try {
			return new SimpleDateFormat(fmt).parse(strDate);
		} catch (Exception e) {
			throw new ConvertException(e);
		}
	}
	
	/** 
	 * 转换字符串到Date
	 * @param str 字符串
	 * @throws FormatException
	 */
	public static Date toDate(String str) throws ConvertException{
		try {
			if(isEmpty(str)) return null;
			return  new SimpleDateFormat(Format.YMDHMS).parse(format2YMDHms(str));
		} catch (Exception e) {
			throw new ConvertException("日期格式化出错:"+str+"."+e.getMessage());
		}
	}
	
	/** 
	 * Object转换为Date
	 * @param obj 实例
	 */
	public static Date toDate0(Object obj) throws ConvertException{
		if(obj==null) return null;
		Class clazz=obj.getClass();
		if(obj instanceof Date) 			return (Date)obj;
		else if(obj instanceof String) 		return toDate((String) obj);
		else throw new ConvertException("不支持到Date类型的转换:"+clazz.getName());
	}
	
	/** 
	 * 获取日历
	 * @param d 日期
	 */
	public static Calendar getCalander(Date d){
		Calendar c=Calendar.getInstance();
		c.setTime(d);
		return c;
	}
	
	/** 
	 * 获取日历
	 * @param d 日期
	 * @throws ConvertException 转换错误
	 */
	public static Calendar getCalander(String d) throws ConvertException{
		return getCalander(toDate(d));
	}
	
	/** 
	 * toString
	 * @param date
	 * @param fmt
	 */
	public static String toString(Date date,String fmt) throws ConvertException{
		try {
			return new SimpleDateFormat(fmt).format(date);
		} catch (Exception e) {
			throw new ConvertException(e);
		}
	}
	
	/** 
	 * toString
	 * @param date
	 */
	public static String toString(Date date) throws ConvertException{
		return toString(date,Format.YMDHMS);
	}
}
